package com.curry.apiprovider.util;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.BitSet;
import java.util.regex.Pattern;

/**
 * Created by zhaoyang on 4/6/16.
 */
public class ISOUtil {
    public static final String[] hexStrings = new String[256];
    public static final Charset CHARSET;
    public static final byte[] EBCDIC2ASCII;
    public static final byte[] ASCII2EBCDIC;
    public static final byte STX = 2;
    public static final byte FS = 28;
    public static final byte US = 31;
    public static final byte RS = 29;
    public static final byte GS = 30;
    public static final byte ETX = 3;

    private ISOUtil() { }

    public static String hexString(byte[] b) {
        StringBuilder d = new StringBuilder(b.length * 2);
        byte[] var2 = b;
        int var3 = b.length;
        for(int var4 = 0; var4 < var3; ++var4) {
            byte aB = var2[var4];
            d.append(hexStrings[aB & 255]);
        }
        return d.toString();
    }

    public static String bitSet2String(BitSet b) {
        int len = b.size();
        len = len > 128?128:len;
        StringBuilder d = new StringBuilder(len);
        for(int i = 0; i < len; ++i) {
            d.append((b.get(i)?'1':'0'));
        }
        return d.toString();
    }

    public static byte[] bitSet2byte(BitSet b) {
        int len = b.length() + 62 >> 6 << 6;
        byte[] d = new byte[len >> 3];
        for(int i = 0; i < len; ++i) {
            if(b.get(i + 1)) {
                d[i >> 3] = (byte)(d[i >> 3] | 128 >> i % 8);
            }
        }
        if(len > 64) {
            d[0] = (byte)(d[0] | 128);
        }
        if(len > 128) {
            d[8] = (byte)(d[8] | 128);
        }
        return d;
    }

    public static byte[] bitSet2byte(BitSet b, int bytes) {
        int len = bytes * 8;
        byte[] d = new byte[bytes];
        for(int i = 0; i < len; ++i) {
            if(b.get(i + 1)) {
                d[i >> 3] = (byte)(d[i >> 3] | 128 >> i % 8);
            }
        }
        if(len > 64) {
            d[0] = (byte)(d[0] | 128);
        }
        if(len > 128) {
            d[8] = (byte)(d[8] | 128);
        }
        return d;
    }

    public static int bitSet2Int(BitSet bs) {
        int total = 0;
        int b = bs.length() - 1;
        if(b > 0) {
            int value = (int)Math.pow(2.0D, (double)b);
            for(int i = 0; i <= b; ++i) {
                if(bs.get(i)) {
                    total += value;
                }
                value >>= 1;
            }
        }
        return total;
    }

    public static BitSet int2BitSet(int value) {
        return int2BitSet(value, 0);
    }

    public static BitSet int2BitSet(int value, int offset) {
        BitSet bs = new BitSet();
        String hex = Integer.toHexString(value);
        hex2BitSet(bs, hex.getBytes(), offset);
        return bs;
    }

    public static BitSet byte2BitSet(byte[] b, int offset, boolean bitZeroMeansExtended) {
        int len = bitZeroMeansExtended?((b[offset] & 128) == 128?128:64):64;
        BitSet bmap = new BitSet(len);
        for(int i = 0; i < len; ++i) {
            if((b[offset + (i >> 3)] & 128 >> i % 8) > 0) {
                bmap.set(i + 1);
            }
        }
        return bmap;
    }

    public static BitSet byte2BitSet(byte[] b, int offset, int maxBits) {
        int len = maxBits > 64?((b[offset] & 128) == 128?128:64):maxBits;
        if(maxBits > 128 && b.length > offset + 8 && (b[offset + 8] & 128) == 128) {
            len = 192;
        }
        BitSet bmap = new BitSet(len);
        for(int i = 0; i < len; ++i) {
            if((b[offset + (i >> 3)] & 128 >> i % 8) > 0) {
                bmap.set(i + 1);
            }
        }
        return bmap;
    }

    public static BitSet byte2BitSet(BitSet bmap, byte[] b, int bitOffset) {
        int len = b.length << 3;
        for(int i = 0; i < len; ++i) {
            if((b[i >> 3] & 128 >> i % 8) > 0) {
                bmap.set(bitOffset + i + 1);
            }
        }
        return bmap;
    }

    public static BitSet hex2BitSet(byte[] b, int offset, boolean bitZeroMeansExtended) {
        int len = bitZeroMeansExtended?((Character.digit((char)b[offset], 16) & 8) == 8?128:64):64;
        BitSet bmap = new BitSet(len);
        for(int i = 0; i < len; ++i) {
            int digit = Character.digit((char)b[offset + (i >> 2)], 16);
            if((digit & 8 >> i % 4) > 0) {
                bmap.set(i + 1);
            }
        }
        return bmap;
    }

    public static BitSet hex2BitSet(byte[] b, int offset, int maxBits) {
        int len = maxBits > 64?((Character.digit((char)b[offset], 16) & 8) == 8?128:64):maxBits;
        if(len > 64 && maxBits > 128 && b.length > offset + 16 && (Character.digit((char)b[offset + 16], 16) & 8) == 8) {
            len = 192;
        }
        BitSet bmap = new BitSet(len);
        for(int i = 0; i < len; ++i) {
            int digit = Character.digit((char)b[offset + (i >> 2)], 16);
            if((digit & 8 >> i % 4) > 0) {
                bmap.set(i + 1);
                if(i == 65 && maxBits > 128) {
                    len = 192;
                }
            }
        }
        return bmap;
    }

    public static BitSet hex2BitSet(BitSet bmap, byte[] b, int bitOffset) {
        int len = b.length << 2;
        for(int i = 0; i < len; ++i) {
            int digit = Character.digit((char)b[i >> 2], 16);
            if((digit & 8 >> i % 4) > 0) {
                bmap.set(bitOffset + i + 1);
            }
        }
        return bmap;
    }

    public static byte[] hex2byte(byte[] b, int offset, int len) {
        byte[] d = new byte[len];
        for(int i = 0; i < len * 2; ++i) {
            int shift = i % 2 == 1?0:4;
            d[i >> 1] = (byte)(d[i >> 1] | Character.digit((char)b[offset + i], 16) << shift);
        }
        return d;
    }

    public static byte[] hex2byte(String s) {
        return s.length() % 2 == 0?hex2byte(s.getBytes(), 0, s.length() >> 1):hex2byte("0" + s);
    }

    public static String byte2hex(byte[] bs) {
        return byte2hex(bs, 0, bs.length);
    }

    public static byte[] int2byte(int value) {
        return value < 0?new byte[]{(byte)(value >>> 24 & 255), (byte)(value >>> 16 & 255), (byte)(value >>> 8 & 255), (byte)(value & 255)}:(value <= 255?new byte[]{(byte)(value & 255)}:(value <= '\uffff'?new byte[]{(byte)(value >>> 8 & 255), (byte)(value & 255)}:(value <= 16777215?new byte[]{(byte)(value >>> 16 & 255), (byte)(value >>> 8 & 255), (byte)(value & 255)}:new byte[]{(byte)(value >>> 24 & 255), (byte)(value >>> 16 & 255), (byte)(value >>> 8 & 255), (byte)(value & 255)})));
    }

    public static int byte2int(byte[] bytes) {
        if(bytes != null && bytes.length != 0) {
            ByteBuffer byteBuffer = ByteBuffer.allocate(4);
            int i;
            for(i = 0; i < 4 - bytes.length; ++i) {
                byteBuffer.put((byte)0);
            }
            for(i = 0; i < bytes.length; ++i) {
                byteBuffer.put(bytes[i]);
            }
            byteBuffer.position(0);
            return byteBuffer.getInt();
        } else {
            return 0;
        }
    }

    public static String int2Hex(int value) {
        return byte2hex(int2byte(value));
    }

    public static int hex2int(String s) {
        return byte2int(hex2byte(s));
    }

    public static String byte2hex(byte[] bs, int off, int length) {
        if(bs.length > off && bs.length >= off + length) {
            StringBuilder sb = new StringBuilder(length * 2);
            byte2hexAppend(bs, off, length, sb);
            return sb.toString().toUpperCase();
        } else {
            throw new IllegalArgumentException();
        }
    }

    public static String fillZeroLeft(String str, int maxLen) {
        if(str.length() >= maxLen) return str;
        int numOfZeros = maxLen - str.length();
        for(int i=0; i<numOfZeros; i++) {
            str = "0" + str;
        }
        return str;
    }

    public static String fillZeroRight(String str, int maxLen) {
        if(str.length() >= maxLen) return str;
        int numOfZeros = maxLen - str.length();
        for(int i=0; i<numOfZeros; i++) str += "0";
        return str;
    }

    public static boolean isSpecNumber(String str, int specLen) {
        if(str == null) return false;
        Pattern pattern = Pattern.compile(("^[0-9]{" + specLen + "}$"));
        return pattern.matcher(str).matches();
    }

    private static void byte2hexAppend(byte[] bs, int off, int length, StringBuilder sb) {
        if(bs.length > off && bs.length >= off + length) {
            sb.ensureCapacity(sb.length() + length * 2);
            for(int i = off; i < off + length; ++i) {
                sb.append(Character.forDigit(bs[i] >>> 4 & 15, 16));
                sb.append(Character.forDigit(bs[i] & 15, 16));
            }
        } else {
            throw new IllegalArgumentException();
        }
    }

    static {
        for(int i = 0; i < 256; ++i) {
            StringBuilder d = new StringBuilder(2);
            char ch = Character.forDigit((byte)i >> 4 & 15, 16);
            d.append(Character.toUpperCase(ch));
            ch = Character.forDigit((byte)i & 15, 16);
            d.append(Character.toUpperCase(ch));
            hexStrings[i] = d.toString();
        }

        CHARSET = Charset.forName("ISO8859_1");
        EBCDIC2ASCII = new byte[]{(byte)0, (byte)1, (byte)2, (byte)3, (byte)-100, (byte)9, (byte)-122, (byte)127, (byte)-105, (byte)-115, (byte)-114, (byte)11, (byte)12, (byte)13, (byte)14, (byte)15, (byte)16, (byte)17, (byte)18, (byte)19, (byte)-99, (byte)10, (byte)8, (byte)-121, (byte)24, (byte)25, (byte)-110, (byte)-113, (byte)28, (byte)29, (byte)30, (byte)31, (byte)-128, (byte)-127, (byte)-126, (byte)-125, (byte)-124, (byte)-123, (byte)23, (byte)27, (byte)-120, (byte)-119, (byte)-118, (byte)-117, (byte)-116, (byte)5, (byte)6, (byte)7, (byte)-112, (byte)-111, (byte)22, (byte)-109, (byte)-108, (byte)-107, (byte)-106, (byte)4, (byte)-104, (byte)-103, (byte)-102, (byte)-101, (byte)20, (byte)21, (byte)-98, (byte)26, (byte)32, (byte)-96, (byte)-30, (byte)-28, (byte)-32, (byte)-31, (byte)-29, (byte)-27, (byte)-25, (byte)-15, (byte)-94, (byte)46, (byte)60, (byte)40, (byte)43, (byte)124, (byte)38, (byte)-23, (byte)-22, (byte)-21, (byte)-24, (byte)-19, (byte)-18, (byte)-17, (byte)-20, (byte)-33, (byte)33, (byte)36, (byte)42, (byte)41, (byte)59, (byte)94, (byte)45, (byte)47, (byte)-62, (byte)-60, (byte)-64, (byte)-63, (byte)-61, (byte)-59, (byte)-57, (byte)-47, (byte)-90, (byte)44, (byte)37, (byte)95, (byte)62, (byte)63, (byte)-8, (byte)-55, (byte)-54, (byte)-53, (byte)-56, (byte)-51, (byte)-50, (byte)-49, (byte)-52, (byte)96, (byte)58, (byte)35, (byte)64, (byte)39, (byte)61, (byte)34, (byte)-40, (byte)97, (byte)98, (byte)99, (byte)100, (byte)101, (byte)102, (byte)103, (byte)104, (byte)105, (byte)-85, (byte)-69, (byte)-16, (byte)-3, (byte)-2, (byte)-79, (byte)-80, (byte)106, (byte)107, (byte)108, (byte)109, (byte)110, (byte)111, (byte)112, (byte)113, (byte)114, (byte)-86, (byte)-70, (byte)-26, (byte)-72, (byte)-58, (byte)-92, (byte)-75, (byte)126, (byte)115, (byte)116, (byte)117, (byte)118, (byte)119, (byte)120, (byte)121, (byte)122, (byte)-95, (byte)-65, (byte)-48, (byte)91, (byte)-34, (byte)-82, (byte)-84, (byte)-93, (byte)-91, (byte)-73, (byte)-87, (byte)-89, (byte)-74, (byte)-68, (byte)-67, (byte)-66, (byte)-35, (byte)-88, (byte)-81, (byte)93, (byte)-76, (byte)-41, (byte)123, (byte)65, (byte)66, (byte)67, (byte)68, (byte)69, (byte)70, (byte)71, (byte)72, (byte)73, (byte)-83, (byte)-12, (byte)-10, (byte)-14, (byte)-13, (byte)-11, (byte)125, (byte)74, (byte)75, (byte)76, (byte)77, (byte)78, (byte)79, (byte)80, (byte)81, (byte)82, (byte)-71, (byte)-5, (byte)-4, (byte)-7, (byte)-6, (byte)-1, (byte)92, (byte)-9, (byte)83, (byte)84, (byte)85, (byte)86, (byte)87, (byte)88, (byte)89, (byte)90, (byte)-78, (byte)-44, (byte)-42, (byte)-46, (byte)-45, (byte)-43, (byte)48, (byte)49, (byte)50, (byte)51, (byte)52, (byte)53, (byte)54, (byte)55, (byte)56, (byte)57, (byte)-77, (byte)-37, (byte)-36, (byte)-39, (byte)-38, (byte)-97};
        ASCII2EBCDIC = new byte[]{(byte)0, (byte)1, (byte)2, (byte)3, (byte)55, (byte)45, (byte)46, (byte)47, (byte)22, (byte)5, (byte)21, (byte)11, (byte)12, (byte)13, (byte)14, (byte)15, (byte)16, (byte)17, (byte)18, (byte)19, (byte)60, (byte)61, (byte)50, (byte)38, (byte)24, (byte)25, (byte)63, (byte)39, (byte)28, (byte)29, (byte)30, (byte)31, (byte)64, (byte)90, (byte)127, (byte)123, (byte)91, (byte)108, (byte)80, (byte)125, (byte)77, (byte)93, (byte)92, (byte)78, (byte)107, (byte)96, (byte)75, (byte)97, (byte)-16, (byte)-15, (byte)-14, (byte)-13, (byte)-12, (byte)-11, (byte)-10, (byte)-9, (byte)-8, (byte)-7, (byte)122, (byte)94, (byte)76, (byte)126, (byte)110, (byte)111, (byte)124, (byte)-63, (byte)-62, (byte)-61, (byte)-60, (byte)-59, (byte)-58, (byte)-57, (byte)-56, (byte)-55, (byte)-47, (byte)-46, (byte)-45, (byte)-44, (byte)-43, (byte)-42, (byte)-41, (byte)-40, (byte)-39, (byte)-30, (byte)-29, (byte)-28, (byte)-27, (byte)-26, (byte)-25, (byte)-24, (byte)-23, (byte)-83, (byte)-32, (byte)-67, (byte)95, (byte)109, (byte)121, (byte)-127, (byte)-126, (byte)-125, (byte)-124, (byte)-123, (byte)-122, (byte)-121, (byte)-120, (byte)-119, (byte)-111, (byte)-110, (byte)-109, (byte)-108, (byte)-107, (byte)-106, (byte)-105, (byte)-104, (byte)-103, (byte)-94, (byte)-93, (byte)-92, (byte)-91, (byte)-90, (byte)-89, (byte)-88, (byte)-87, (byte)-64, (byte)79, (byte)-48, (byte)-95, (byte)7, (byte)32, (byte)33, (byte)34, (byte)35, (byte)36, (byte)37, (byte)6, (byte)23, (byte)40, (byte)41, (byte)42, (byte)43, (byte)44, (byte)9, (byte)10, (byte)27, (byte)48, (byte)49, (byte)26, (byte)51, (byte)52, (byte)53, (byte)54, (byte)8, (byte)56, (byte)57, (byte)58, (byte)59, (byte)4, (byte)20, (byte)62, (byte)-1, (byte)65, (byte)-86, (byte)74, (byte)-79, (byte)-97, (byte)-78, (byte)106, (byte)-75, (byte)-69, (byte)-76, (byte)-102, (byte)-118, (byte)-80, (byte)-54, (byte)-81, (byte)-68, (byte)-112, (byte)-113, (byte)-22, (byte)-6, (byte)-66, (byte)-96, (byte)-74, (byte)-77, (byte)-99, (byte)-38, (byte)-101, (byte)-117, (byte)-73, (byte)-72, (byte)-71, (byte)-85, (byte)100, (byte)101, (byte)98, (byte)102, (byte)99, (byte)103, (byte)-98, (byte)104, (byte)116, (byte)113, (byte)114, (byte)115, (byte)120, (byte)117, (byte)118, (byte)119, (byte)-84, (byte)105, (byte)-19, (byte)-18, (byte)-21, (byte)-17, (byte)-20, (byte)-65, (byte)-128, (byte)-3, (byte)-2, (byte)-5, (byte)-4, (byte)-70, (byte)-82, (byte)89, (byte)68, (byte)69, (byte)66, (byte)70, (byte)67, (byte)71, (byte)-100, (byte)72, (byte)84, (byte)81, (byte)82, (byte)83, (byte)88, (byte)85, (byte)86, (byte)87, (byte)-116, (byte)73, (byte)-51, (byte)-50, (byte)-53, (byte)-49, (byte)-52, (byte)-31, (byte)112, (byte)-35, (byte)-34, (byte)-37, (byte)-36, (byte)-115, (byte)-114, (byte)-33};
    }
}

